﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Kokomo.NeuralNets
{
	public class Net
	{
		public int InputCount { get; private set; }
		protected Layer[] Layers { get; private set; }
		public Layer OutputLayer { get; private set; }

		public Net(int inputCount, int[] layerSizes)
		{
			ArgumentValidation.CheckMinimum("inputCount", inputCount, 1);
			ArgumentValidation.CheckNullArgument("layerSizes", layerSizes);

			this.InputCount = inputCount;

			int previousSize = inputCount;
			this.Layers = new Layer[layerSizes.Length];
			for (int i = 0; i < this.Layers.Length; i++)
			{
				int size = layerSizes[i];
				Layer layer = new Layer(size, previousSize + 1);
				previousSize = size;
			}
		}

		protected void ValidateInputVector(double[] inputVector)
		{
			ArgumentValidation.CheckNullArgument("inputVector", inputVector);
			if (inputVector.Length != this.InputCount)
			{
				throw new ArgumentException("Incorrect sized inputVector", "inputVector");
			}
		}

		public double[] Activate(double[] inputVector)
		{
			this.ValidateInputVector(inputVector);

			foreach (var layer in this.Layers)
			{
				double[] inputs = new double[inputVector.Length + 1];
				Array.Copy(inputVector, inputVector, inputVector.Length);
				inputVector = layer.Activate(inputs);
			}

			return inputVector;
		}

		public void Train(double[] inputVector, double[] expectedOutput)
		{
			this.ValidateInputVector(inputVector);

			double[][] outputVectors = new double[this.Layers.Length][];
			for (int i = 0; i < this.Layers.Length; i++)
			{
				Layer layer = this.Layers[i];
				double[] inputs = new double[inputVector.Length + 1];
				Array.Copy(inputVector, inputVector, inputVector.Length);
				outputVectors[i] = inputVector = layer.Activate(inputs);
			}


		}
	}
}
